#!/usr/bin/env python3
"""日期时间处理的工具类
"""

from datetime import datetime, time
import chinese_calendar
from functools import wraps, partial
from dateutil.parser import parse


def now():
    """当前时间戳"""
    return int(datetime.now().timestamp())


def timestamp():
    """时间戳"""
    return datetime.now().timestamp()


def make_timestamp(year=None, month=None, day=None, hour=0, minute=0, second=0):
    n = datetime.now()
    if year is None:
        year = n.year
    if month is None:
        month = n.month
    if day is None:
        day = n.day
    t = datetime(year, month, day, hour, minute, second).timestamp()
    return int(t)


def today_timestamp():
    """获取当天零点的时间戳

  Returns:
    int: 当天零点的时间戳，精确到秒
  """
    nw = datetime.now().replace(hour=0, minute=0, second=0)
    return int(nw.timestamp())


def format(pattern="%Y-%m-%d %H:%M:%S", t=None) -> str:
    """将时间戳格式化为指定格式的字符串形式

  Args:
      :param pattern:
      :param t:

  Returns:
      str: 正确格式化后的日期字符串
  """
    if t is None:
        return datetime.now().strftime(pattern)
    return datetime.fromtimestamp(t).strftime(pattern)


def to_timestamps(s, pattern):
    return int(datetime.strptime(s, pattern).timestamp())


def parse_from_string(s: str) -> int:
    return int(parse(s).timestamp())


def timing(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        startTime = now()
        result = func(*args, **kwargs)
        endTime = now()
        costTime = endTime - startTime
        if costTime < 60:
            costStr = f'{costTime} 秒'
        elif 3600 > costTime >= 60:
            costStr = f'{costTime / 60} 分'
        else:
            costStr = f'{costTime / 3600} 小时'
        # print(f"{func.__name__} 耗时 {costStr}. 参数{args = } {kwargs = }. ")
        print(f"{func.__name__} 耗时 {costStr}. ")
        return result

    return wrapper


def is_trading_day(t=None):
    tms = now() if t is None else t
    dt = datetime.fromtimestamp(tms)
    if dt.isoweekday() <= 5 and chinese_calendar.is_workday(dt):
        return True
    else:
        return False


def is_trading_time(t=None):
    tms = now() if t is None else t
    if not is_trading_day(tms):
        return False
    nowTime = datetime.fromtimestamp(tms).time()
    if (time(hour=9, minute=30) < nowTime < time(hour=11, minute=30)) or (time(hour=13) < nowTime < time(hour=15)):
        return True
    return False


def is_after_open(t=None):
    tms = now() if t is None else t
    if not is_trading_day(tms):
        return False
    nowTime = datetime.fromtimestamp(tms).time()
    if nowTime >= time(hour=9, minute=30):
        return True
    return False


def is_before_open(t=None):
    tms = now() if t is None else t
    if not is_trading_day(tms):
        return False
    nowTime = datetime.fromtimestamp(tms).time()
    if nowTime < time(9, 30):
        return True
    return False


def is_before_close(t=None):
    tms = now() if t is None else t
    if not is_trading_day(tms):
        return False
    nowTime = datetime.fromtimestamp(tms).time()
    if nowTime < time(15):
        return True
    return False


def is_after_close(t=None):
    tms = now() if t is None else t
    if not is_trading_day(tms):
        return False
    nowTime = datetime.fromtimestamp(tms).time()
    if nowTime >= time(15):
        return True
    return False


def previous_trading_day(t=None):
    if t is None:
        t = today_timestamp()
    t -= 86400
    if is_trading_day(t):
        return t
    else:
        return previous_trading_day(t)


def next_trading_day(t=None):
    if t is None:
        t = today_timestamp()
    t += 86400
    if is_trading_day(t):
        return t
    else:
        return next_trading_day(t)


def previous_no_trade_day(t=None):
    if t is None:
        t = today_timestamp()
    t -= 86400
    if is_trading_day(t):
        return previous_no_trade_day(t)
    else:
        return t


def get_trade_days(days: int = -1, fmt: bool = False):
    tradeDays = []
    count = 0
    tms = today_timestamp()
    if days == 0:
        if is_trading_day(tms):
            tradeDays.append(tms)
    elif days > 0:
        while count < days:
            tms = next_trading_day(tms)
            count += 1
            tradeDays.append(tms)
    else:
        while count < abs(days):
            tms = previous_trading_day(tms)
            count += 1
            tradeDays.append(tms)

    return tradeDays if not fmt else list(map(partial(format, '%Y%m%d'), tradeDays))


if __name__ == '__main__':
    res = get_trade_days(-11, True)
    print(res)
